package com.zxy.ziems.server.budget.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zxy.btp.mybatis.base.BtpBaseServiceImpl;
import com.zxy.ziems.server.budget.convertor.BudgetValueConvertor;
import com.zxy.ziems.server.budget.mapper.BudgetValueMapper;
import com.zxy.ziems.server.budget.pojo.dto.BudgetDefDTO;
import com.zxy.ziems.server.budget.pojo.dto.BudgetValDTO;
import com.zxy.ziems.server.budget.pojo.entity.BudgetDefEntity;
import com.zxy.ziems.server.budget.pojo.entity.BudgetValueEntity;
import com.zxy.ziems.server.budget.service.BudgetDefService;
import com.zxy.ziems.server.budget.service.BudgetValueService;
import com.zxy.ziems.server.log.DataRecordTypeEnum;
import com.zxy.ziems.server.log.pojo.entity.DataRecordLogEntity;
import com.zxy.ziems.server.log.service.DataRecordService;
import com.zxy.ziems.server.mybatis.core.query.QueryWrapperX;
import com.zxy.ziems.server.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class BudgetValueServiceImpl extends BtpBaseServiceImpl<BudgetValueMapper, BudgetValueEntity> implements BudgetValueService {

    @Autowired
    private BudgetDefService budgetDefService;
    @Autowired
    private DataRecordService dataRecordService;

    @Override
    public List<BudgetValueEntity> getByBudgetDefIds(List<String> budgetDefIds) {
        QueryWrapper<BudgetValueEntity> param = new QueryWrapper<>();
        param.lambda().in(BudgetValueEntity::getBudgetDefId, budgetDefIds);
        return baseMapper.selectList(param);
    }

    @Transactional
    @Override
    public void add(BudgetDefDTO budgetDefDTO) {
        doSaveBeforeAction(budgetDefDTO);

        List<BudgetValueEntity> entities = BudgetValueConvertor.INSTANT.dtoList2EntityList(budgetDefDTO.getBudgetValDTOList());

        addLog(budgetDefDTO);
        baseMapper.addOrUpdate(entities);
    }

    private void addLog(BudgetDefDTO budgetDefDTO) {
        List<DataRecordLogEntity> logs = new ArrayList<>();
        List<BudgetValueEntity> budgetValueEntities = baseMapper.selectList(BudgetValueEntity::getBudgetDefId, budgetDefDTO.getBudgetDefId());
        List<BudgetValDTO> budgetValDTOList = budgetDefDTO.getBudgetValDTOList();
        Map<String, BudgetValDTO> newMap = budgetValDTOList.stream().collect(Collectors.toMap(BudgetValDTO::getBudgetMonth, v -> v));
        Map<String, BudgetValueEntity> oldMap = budgetValueEntities.stream().collect(Collectors.toMap(k -> String.format("%02d", k.getBudgetMonth()), v -> v, (e, e1) -> e));
        newMap.forEach((k, v) -> {
            DataRecordLogEntity log = new DataRecordLogEntity();
            BudgetValueEntity budgetValueEntity = oldMap.get(k);
            log.setTag(k + "月");
            if (budgetValueEntity == null) {
                log.setNewData(v.getBudgetVal().toString());
                logs.add(log);
            } else if (budgetValueEntity.getBudgetVal().compareTo(v.getBudgetVal()) != 0){
                log.setOldData(budgetValueEntity.getBudgetVal().toString());
                log.setNewData(v.getBudgetVal().toString());
                logs.add(log);
            }
        });
        BudgetDefEntity en = budgetDefService.getById(budgetDefDTO.getBudgetDefId());
        dataRecordService.add(DataRecordTypeEnum.BUDGET_MODIFY, en.getTag(), budgetDefDTO.getBudgetDefId(), logs);
    }

    private void doSaveBeforeAction(BudgetDefDTO budgetDefDTO) {
        AssertUtil.nonNull(budgetDefService.getById(budgetDefDTO.getBudgetDefId()), "未找到预算条目");
        List<BudgetValDTO> budgetValDTOList = budgetDefDTO.getBudgetValDTOList();
        AssertUtil.isFalse(budgetValDTOList.size() > 12, "参数错误");
        budgetValDTOList.forEach(m -> m.setBudgetDefId(budgetDefDTO.getBudgetDefId()));
    }

    @Override
    public void deleteByBudgetDefIds(List<String> budgetDefIds) {
        QueryWrapper<BudgetValueEntity> param = new QueryWrapperX<>();
        param.lambda().in(BudgetValueEntity::getBudgetDefId, budgetDefIds);
        baseMapper.delete(param);
    }
}
